查找(AVL平衡二叉树)

【1】为什么需要平衡二叉树?

矛盾是推进事物向前发展的源动力。

那么平衡二叉树是从哪里来?肯定是有矛盾存在的。请看下面的分析:

【2】什么是平衡二叉树?

平衡二叉树的基本认识:

【3】平衡二叉树的构建原理

平衡二叉树的形成肯定是有一定规律可循的,那么平衡二叉树的“生长”原理是什么呢?

请看程老师下面的构建示例以及详细讲解:

关于平衡二叉树的旋转分为以下四种情况:

【4】平衡二叉树的实现

平衡二叉树的实现代码如下:

  1 #include <iostream>
  2 using namespace std;
  3 
  4 template<class Type> 
  5 class AVLtree;           
  6 
  7 template<class Type>
  8 class TNode
  9 {
 10     friend  class  AVLtree<Type>;
 11 private:
 12     Type  data;
 13     int   balance;    // 平衡因子
 14     TNode<Type> *leftChild, *rightChild;
 15 public:
 16     TNode(const Type &x =  Type(),TNode<Type> *left = NULL,TNode<Type> *right = NULL)
 17         : data(x)
 18         , leftChild(left)
 19         , rightChild(right)
 20         , balance(0)
 21     {}
 22 };
 23 
 24 template<class Type>
 25 class AVLtree
 26 {
 27 private:
 28     TNode<Type>  *root;
 29 private:
 30     void RightBalance(TNode<Type> * &r,bool  &action);
 31     void LeftBalance(TNode<Type> *&r,bool &action);
 32     void Insert(TNode<Type> * &root,const Type &x,bool &action);
 33     void LeftLeft(TNode<Type> * &r);
 34     void RightRight(TNode<Type> * &r);
 35     void LeftRight(TNode<Type> *&r);
 36     void RightLeft(TNode<Type> *&r);
 37     TNode<Type> *Parent(TNode<Type> *p,TNode<Type> *cur);
 38     TNode<Type> *FindNodeNext(TNode<Type> *cur);
 39     void DeleTNode(TNode<Type> *&cur,TNode<Type> *par);
 40     void Remove(TNode<Type> * &r,const Type &x,bool &action);
 41     void InOrder(TNode<Type> *p);
 42 public:
 43     AVLtree();
 44     void Insert(const Type &bt);
 45     TNode<Type> *Parent(TNode<Type> *cur);
 46     void Remove(const Type &x);
 47     void InOrder();
 48 };
 49 
 50 // 右平衡处理过程
 51 template<class Type>
 52 void AVLtree<Type>::RightBalance(TNode<Type> * &r, bool &action)
 53 {
 54     TNode<Type> *rightsub = r->rightChild, *leftsub = NULL;
 55     switch (rightsub->balance)   //判断右子树的平衡因子
 56     {
 57         case -1: // RR型
 58             r->balance = 0;
 59             rightsub->balance = 0;
 60             RightRight(r);   //RR型处理
 61             action = false;
 62             break;
 63         case 0:
 64             break;
 65         case 1: // RL型
 66             leftsub = rightsub->leftChild;  
 67             switch (leftsub->balance) // 判断左子树的平衡因子
 68             {
 69                 case 0: // RL型
 70                     r->balance = 0;
 71                     rightsub->balance = 0;
 72                     leftsub->balance = 0;
 73                     break;
 74                 case 1: // RLL型
 75                     r->balance = 0;
 76                     leftsub->balance = 0;
 77                     rightsub->balance = -1;
 78                     break;
 79                 case -1: // RLR型
 80                     rightsub->balance = 0;
 81                     leftsub->balance = 0;
 82                     r->balance= -1;
 83                     break;
 84             }
 85             RightLeft(r);  // RL折线型转换处理
 86             action = false;
 87             break;
 88     }
 89 }
 90 // 折线型LR处理
 91 template<class Type>
 92 void AVLtree<Type>::LeftRight(TNode<Type> *&r)
 93 {
 94     RightRight(r->leftChild); // 转换为LL型(一条直线)
 95     LeftLeft(r);  // LL型处理
 96 }
 97 // 折线型RL处理
 98 template<class Type>
 99 void AVLtree<Type>::RightLeft(TNode<Type> *&r)
100 {
101     LeftLeft(r->rightChild);  // 先转换为RR型(一条直线)
102     RightRight(r);  // RR型处理
103 }
104 // 1. 把RL转换为RR  2. LL型处理
105 template<class Type>
106 void AVLtree<Type>::LeftLeft(TNode<Type> * &r) 
107 {
108     TNode<Type> *cur = r;          // cur暂存r
109     r = r->leftChild;              // 改变r就是改变根
110     cur->leftChild = r->rightChild;// 改变暂存cur  实现衔接
111     r->rightChild = cur;           // 根的右子树置为cur
112 }
113 // 1. 把LR转换为LL  2. RR型处理
114 template<class Type>
115 void AVLtree<Type>::RightRight(TNode<Type> * &r)
116 {
117     TNode<Type> *cur = r;          // cur暂存r
118     r = r->rightChild;             // 改变r就是改变根
119     cur->rightChild = r->leftChild;// 改变暂存cur  实现衔接
120     r->leftChild = cur;            // 根的左子树置为cur
121 }
122 // 左平衡处理过程
123 template<class Type>
124 void AVLtree<Type>::LeftBalance(TNode<Type> *&r, bool &action)
125 {
126     TNode<Type> *leftsub = r->leftChild;
127     TNode<Type> *rightsub = leftsub->rightChild;
128     switch (leftsub->balance)
129     {
130         case 1:// LL型
131             leftsub->balance = 0;
132             r->balance = 0;
133             LeftLeft(r);
134             action = false;
135             break;
136         case 0:
137             action = false;
138             break;
139         case -1:// LR型
140             switch (rightsub->balance)
141             {
142             case 0:// LR型
143                 r->balance = 0;
144                 rightsub->balance = 0;
145                 leftsub->balance = 0;
146                 break;
147             case -1:// LRR型
148                 r->balance = 0;
149                 rightsub->balance = 0;
150                 leftsub->balance = 1;
151                 break;
152             case 1:// LRL型
153                 rightsub->balance = 0;
154                 leftsub->balance = 0;
155                 r->balance = -1;
156                 break;
157             }
158             LeftRight(r);  // LR折线型转换处理
159             action = false;
160             break;
161         }
162 }
163 // Insert主函数
164 template<class Type>
165 void AVLtree<Type>::Insert(TNode<Type> * & root, const Type &x, bool &action)
166 {
167     if (NULL == root)
168     {
169         root = new TNode<Type>(x);
170         return;
171     }
172     else if (x > root->data)
173     {
174         Insert(root->rightChild, x, action);
175         if (action) // 右子树插入成功
176         {
177             switch (root->balance)  // 需要重置根的平衡因子
178             {
179                 case 1: // 表示左子树已经存在,现再插入右子树成功
180                     root->balance = 0;  //平衡因子置0
181                     break;
182                 case 0: // 表示之前平衡,现再插入右子树成功
183                     root->balance = -1;  //平衡因子置1
184                     break;
185                 case -1: // 表示右子树已经存在,现再插入右子树成功
186                     RightBalance(root, action);    //右平衡
187                     break;
188             }
189         }
190     }
191     else if (x < root->data)
192     {
193         Insert(root->leftChild, x, action);
194         if (action)  // 左子树插入成功
195         {
196             switch (root->balance)    // 需要重置根的平衡因子
197             {
198             case 1: // 平衡左子树
199                 LeftBalance(root, action);
200                 break;
201             case 0:
202                 root->balance = 1;
203                 break;
204             case -1:
205                 root->balance = 0;
206                 action = false;
207                 break;
208             }
209         }
210     }
211     else
212         cout << "数据" << x << "重复!" << endl;
213 }
214 // 查找当前节点的父节点
215 template<class Type>
216 TNode<Type> *AVLtree<Type>::Parent(TNode<Type> *p, TNode<Type> *cur)
217 {
218     if (NULL == p || NULL == cur|| p == cur)
219         return NULL;
220     if (cur == p->leftChild || cur == p->rightChild)
221         return p;
222 
223     if (p->data < cur->data)
224         return Parent(p->rightChild, cur);
225     else
226         return Parent(p->leftChild, cur);
227 }
228 // 查找当前结点的后继 (先序遍历的后继)
229 template<class Type>
230 TNode<Type> *AVLtree<Type>::FindNodeNext(TNode<Type> *cur)
231 {
232     if (NULL == cur) 
233         return NULL;
234     TNode<Type> *p = cur->rightChild;
235     while (p->leftChild != NULL)
236     {
237         p = p->leftChild;
238     }
239     return p;
240 }
241 //////////////////////////////////////////////////////////////////////
242 /////////////////////////////////删除节点
243 template<class Type>
244 void AVLtree<Type>::DeleTNode(TNode<Type> *&cur, TNode<Type> *par)
245 {
246     if (NULL == cur)   
247         return;
248     //    情况一:删除的是根节点,那么它的父节点必定为NULL
249     if (NULL == par)
250     {    // cur可能是根结点,并且树仅仅只有一个根
251         if (NULL == cur->rightChild && NULL == cur->leftChild)
252         {
253             delete cur;
254             cur = NULL;
255             return;
256         }
257         // 单分支的树
258         if (NULL == cur->rightChild)
259         {    // 右子树不存在
260             TNode<Type> *p = cur;
261             cur = cur->leftChild;
262             delete p;
263             p = NULL;
264             return;
265         }
266         if (NULL == cur->leftChild)
267         {    // 左子树不存在
268             TNode<Type> *q = cur;
269             cur = cur->rightChild;
270             delete q;
271             q = NULL;
272             return;
273         }
274     }
275     // 情况二:删除的属于双分支的节点
276     if (cur->leftChild != NULL && cur->rightChild != NULL)
277     {
278         TNode<Type> *p = FindNodeNext(cur); // 锁定先序遍历的后继
279         // 情况一:
280         if (cur->rightChild == p)
281         {    // 说明右子树仅仅只有一个节点
282             cur->balance += 1;    // 删除之后平衡因子改变
283             cur->data = p->data;  // 填充数据,意味着改变删除对象
284             cur->rightChild = p->rightChild; // 衔接数据
285             delete p;  //删除节点p
286             p = NULL;
287             return;
288         }
289         // 情况二:
290         // 否则
291         TNode<Type> *q = Parent(p); // 找到父节点
292         if (q->balance != 0)  // 不等于0,说明删除后会影响根结点的平衡因子
293           cur->balance += 1;    // 调整根节点的平衡因子
294         // 否则
295         q->balance -= 1;   // 删除的是左节点,所以加一
296         cur->data = p->data; // 填充数据,意味着改变删除对象
297         
298         q->leftChild = p->rightChild; // 衔接数据
299 
300         // 最后才可以动手删除节点  删除节点  释放内存
301         delete p;
302         p = NULL;
303         return;
304     }
305     // 情况三:单分支(其中包括了叶子节点的情况)
306     if (NULL == cur->leftChild)
307     {
308         TNode<Type> *p = cur;
309         if (cur == par->leftChild)
310             par->leftChild = cur->rightChild;  // 衔接数据
311         else 
312             par->rightChild = cur->rightChild; // 衔接数据
313 
314         delete p;
315         p = NULL;
316         return;
317     }
318     if (NULL == cur->rightChild)
319     {
320         TNode<Type> *q = cur; 
321         if (cur == par->leftChild)
322             par->leftChild = cur->leftChild;
323         else 
324             par->rightChild = cur->leftChild;
325 
326         delete q;
327         q = NULL;
328         return;
329     }
330 }
331 // 删除过程的主函数
332 template<class Type>
333 void AVLtree<Type>::Remove(TNode<Type> * &r, const Type &x, bool &action)
334 {
335     if (NULL == r)    
336         return;
337     if (x == r->data)
338     {
339         TNode<Type> *cur = r; // 确定数据的节点信息
340         TNode<Type> *par = Parent(r);// 确定当前结点的父节点
341         DeleTNode(r, par); // 删除当前指针
342         return;
343     }
344     else if (x > r->data)
345     {    // 右边查找
346         Remove(r->rightChild, x, action);
347         if (action)
348         {
349             switch (r->balance)
350             {
351             case -1: // 若原来为1,现在删除了右节点,应该为0
352                 r->balance = 0;
353                 break;
354                 //若原来为-1,现在又再右枝上删除了节点,  
355                 //树一定不平衡,需要左平衡调整
356             case 1:   
357                 LeftBalance(r, action);
358                 action = false;
359                 break;
360             case 0: // 若原来为0,现在删除了右节点,应该为-1
361                 r->balance = 1;
362                 action = false;
363                 break;
364             }
365         }
366     }
367     else if (x < r->data)
368     {
369         Remove(r->leftChild, x, action);
370         if (action)
371         {
372             switch (r->balance)
373             {
374             case -1:// 若原来为1,现在又再左枝上删除了节点,
375                     // 树一定不平衡,需要右平衡调整
376                 RightBalance(r, action);
377                 break;
378             case 1:// 若原来为-1,现在删除了左节点,应该为0
379                 r->balance = 0;
380                 break;
381             case 0:// 若原来为0,现在删除了左节点,应该为1
382                 r->balance = -1;
383                 action = false;
384                 break;
385             }
386         }
387     }
388 }
389 
390 template<class Type>
391 AVLtree<Type>::AVLtree(): root(NULL)
392 {}
393 template<class Type>
394 void AVLtree<Type>::Insert(const Type &bt)
395 {
396     bool action = true;
397     Insert(root, bt, action);
398 }
399 template<class Type>
400 TNode<Type> *AVLtree<Type>::Parent(TNode<Type> *cur)
401 {
402     return Parent(root, cur);
403 }
404 template<class Type>
405 void AVLtree<Type>::Remove(const Type &x)
406 {
407     bool action = true;
408     Remove(root, x, action);
409 }
410 template<class Type>
411 void AVLtree<Type>::InOrder(TNode<Type> *p)
412 {
413     if (p != NULL)
414     {
415         InOrder(p->leftChild);
416         cout << p->data << " ";
417         InOrder(p->rightChild);
418     }
419 }
420 template<class Type>
421 void AVLtree<Type>::InOrder()
422 {
423     InOrder(root);
424     cout << endl;
425 }
View Code

 

Good  Good Study, Day  Day  Up.

顺序  选择  循环  总结

posted @ 2013-12-10 13:56  kaizenly  阅读(1469)  评论(3编辑  收藏  举报
打赏